package com.geezdata.cps.ttk_admin.api.util;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.geezdata.cps.base.enums.ErrorCode;
import com.geezdata.cps.base.response.BaseResponse;
import com.geezdata.cps.base.utils.Md5Util;
import com.geezdata.cps.ttk.common.response.LoginResult;
import com.geezdata.cps.ttk.common.vo.UserResVO;
import com.geezdata.cps.ttk.query.query.UserService;

@Service("loginManager")
public class LoginManager {	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
    private UserService userService;
	
	public BaseResponse<LoginResult> login(String username, String password) {
		UserResVO userVO = userService.getUserDetailByUserName(username, 1);
		if (userVO == null) {
			return BaseResponse.error(ErrorCode.NONEXISTENT_USERNAME.getCode(), ErrorCode.NONEXISTENT_USERNAME.getDesc());
		}

		return internalLogin(userVO, Md5Util.md5(userVO.getSalt() + password));
	}
	
	private BaseResponse<LoginResult> internalLogin(UserResVO userVO, String password) {
		String username = userVO.getUserName();
		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //获取当前的Subject  
        Subject currentUser = SecurityUtils.getSubject();  
        try {  
            //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查  
            //每个Realm都能在必要时对提交的AuthenticationTokens作出反应  
            //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法 
        	if(currentUser.isAuthenticated() && !username.equals(currentUser.getPrincipal())) {
        		logger.info("同一个浏览器登录不同账号. " + username + " | " + currentUser.getPrincipal());
        	}
        	
        	currentUser.logout(); 
            logger.info("对用户[" + username + "]进行登录验证..验证开始");  
            currentUser.login(token);  
            logger.info("对用户[" + username + "]进行登录验证..验证通过");  
        }catch(UnknownAccountException uae){  
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户");  
            return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), "未知账户");
        }catch(IncorrectCredentialsException ice){  
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证"); 
            return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), "密码不正确");
        }catch(LockedAccountException lae){  
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");  
            return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), "账户已锁定");
        }catch(ExcessiveAttemptsException eae){  
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多"); 
            return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), "用户名或密码错误次数过多");
        }catch(AuthenticationException ae){  
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下", ae);  
            return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), "用户名或密码不正确");
        }  
        //验证是否登录成功  
        if(currentUser.isAuthenticated()) {  
            logger.info("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");  
            currentUser.hasRole("This is a trick, which is used to initialized userRolesAndPermissions cache");
            LoginResult result = new LoginResult();
            result.setUser(userVO);
            return BaseResponse.success(result);
        } else {
            token.clear();
            return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), "登录认证失败，请重新登录");
        }
	}
}